home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Toolbox / Visual Basic Toolbox (P.I.E.)(1996).ISO / arrays / hugearay / hugearr.c < prev    next >
Encoding:
Text File  |  1992-09-11  |  15.7 KB  |  379 lines

  1. Date:  10-Sep-92 11:01 PDT
  2. From:  Gary Garrison [76400,3555]
  3. Subj:  HUGEARR.C
  4.  
  5. /************************************************************************
  6. *                                                                       *
  7. *                               HUGEARR.DLL                             *
  8. *                                                                       *
  9. *               Huge array support for Microsoft Visual Basic           *
  10. *                                                                       *
  11. *                             By Mike Warning                           *
  12. *                                                                       *
  13. ************************************************************************/
  14.  
  15. #include <memory.h>
  16. #include <windows.h>
  17. #include "hugearr.h"
  18.  
  19. HANDLE                  hLocalMem;              // handle to local memory
  20. int                     NumArrays;              // total number of arrays
  21.  
  22. /************************************************************************
  23. * LibMain -                                                             *
  24. *   Standard DLL constructor.  Allocates all of local heap to store     *
  25. * array descriptors and then set the total number of arrays possible.   *
  26. ************************************************************************/
  27. int FAR pascal
  28.      LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  29. {
  30.     if (cbHeapSize > 0)
  31.     UnlockData(0);
  32.                     // Allocate memory for array descrips.
  33.     hLocalMem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  34.                          LocalCompact((WORD) 65500));
  35.     if (hLocalMem == NULL)
  36.     return 0;                       // Something happened, bomb out
  37.                     // calc total number of arrays
  38.     NumArrays = (int) (LocalSize(hLocalMem) / sizeof(struct ArrayDesc));
  39.     return (1);
  40. }
  41.  
  42. /************************************************************************
  43. * WEP -                                                                 *
  44. *   Standard DLL destructor.  Free up local memory and quit.            *
  45. ************************************************************************/
  46. int FAR pascal WEP(int bSystemExit)
  47. {
  48.     LocalFree(hLocalMem);
  49.     return (1);
  50. }
  51.  
  52. /************************************************************************
  53. * HugeDim -                                                             *
  54. *   Dimensions a new array.  The size of the array is                   *
  55. * (recsize * ubound+1). Recsize is the size in bytes of each element in *
  56. * the array and ubound is the upper bound of the array. All arrays have *
  57. * a lower bound of 0.                                                   *
  58. *                                                                       *
  59. * Note: If total size of the array is greater than 64k, recsize should  *
  60. *       be an integer power of two (1,2,4,8,16,etc.)  Otherwise, the    *
  61. *       huge pointers will not be added correctly.                      *
  62. ************************************************************************/
  63. int FAR pascal _export HugeDim(int recsize, long ubound)
  64. {
  65.     int         hArray;                 // handle to array to dimension
  66.     pDescrip    pArray;                 // pointer to array descriptor
  67.     int         ret;                    // return value from HugeAlloc
  68.  
  69.     pArray = (pDescrip) LocalLock(hLocalMem);   // find a free array
  70.     if ((hArray = GetFreeArray(pArray)) == HA_TOMANYARRAYS)  {
  71.     LocalUnlock(hLocalMem);                 // couldn't find one,
  72.     return (HA_TOMANYARRAYS);               // return error.
  73.     }
  74.                     // allocate new array
  75.     ret = HugeAlloc(pArray + hArray, recsize, ubound, FALSE);
  76.     LocalUnlock(hLocalMem);
  77.  
  78.     if (ret < 0)                        // if an error occured during alloc
  79.     return (ret);                   // return the error, else
  80.     else
  81.     return (hArray);                // return the handle to the array
  82. }
  83.  
  84. /************************************************************************
  85. * HugeRedim -                                                           *
  86. *   Redimenions the given array to have the new 'ubound'.  The old      *
  87. * recsize is kept.  All data in the array is preserved and any new data *
  88. * (created by expanding the array) is initialized to 0.                 *
  89. *                                                                       *
  90. * Note: The recsize must be an integer power of two if the total array  *
  91. *       size is greater than 64k.                                       *
  92. ************************************************************************/
  93. int FAR pascal _export HugeRedim(int hArray, long ubound)
  94. {
  95.     pDescrip    pArray;                 // pointer to array desciptor
  96.     register    ret;                    // return code of HugeAlloc
  97.  
  98.     if (hArray < 0 | hArray >= NumArrays)
  99.     return (HA_BADARRAY);           // illegal array handle
  100.  
  101.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  102.  
  103.     if (pArray -> handle != NULL)       // reallocate array
  104.     ret = HugeAlloc(pArray, pArray -> recsize, ubound, TRUE);
  105.     else
  106.     ret = HA_BADARRAY;              // array has never been allocated
  107.  
  108.     LocalUnlock(hLocalMem);
  109.     return (ret);
  110. }
  111.  
  112.  
  113. /********************************************************************
  114. * GetFreeArray -                                                    *
  115. *   Searches the array descriptor table looking for a free entry.   *
  116. * It returns the index into the table if an entry is free or        *
  117. * HA_TOMANYARRAYS otherwise.  pArray is the pointer to the start of *
  118. * the table.                                                        *
  119. ********************************************************************/
  120. int GetFreeArray(pDescrip pArray)
  121. {
  122.     int i = 0;
  123.                     // loop until found or out of entries
  124.     while ((i < NumArrays) && (pArray -> handle != NULL))  {
  125.     ++pArray;
  126.     ++i;
  127.     }
  128.  
  129.     if (i == NumArrays)                 // didn't find a spot
  130.     return (HA_TOMANYARRAYS);
  131.  
  132.     return (i);                         // found one, return index to it
  133. }
  134.  
  135. /********************************************************************
  136. * GetHugeEl -                                                       *
  137. *   Retrieves an element of the array storing it into the buffer    *
  138. * pointed to by 'buffer'.  hArray is the index into the descriptor  *
  139. * table of the array, element is the element to get.                *
  140. *                                                                   *
  141. * NOTE: there is absolutely no type checking done on the buffer.    *
  142. *       It is up to the programmer to make sure it points to the    *
  143. *       correct data type.                                          *
  144. ********************************************************************/
  145. int FAR pascal _export GetHugeEl(int hArray, long element, BYTE FAR *buffer)
  146. {
  147.     BYTE _huge          *ptr;               // pointer to array element
  148.     pDescrip            pArray;             // pointer to array descriptor
  149.  
  150.     if (hArray < 0 || hArray >= NumArrays)
  151.     return (HA_BADARRAY);               // illegal array handle
  152.  
  153.                         // point to proper descriptor
  154.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  155.  
  156.     if (pArray -> handle == NULL)  {
  157.     LocalUnlock(hLocalMem);
  158.     return (HA_BADARRAY);               // array hasn't been allocated
  159.     }
  160.     if ((pArray -> ubound < element) || (element < 0))  {
  161.     LocalUnlock(hLocalMem);
  162.     return (HA_SUBSCRIPT);              // subscript out of range
  163.     }
  164.                         // calculate pointer to element
  165.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  166.     ptr = ptr + element * pArray->recsize;
  167.     _fmemcpy(buffer, ptr, pArray -> recsize);   // copy data
  168.  
  169.     GlobalUnlock(pArray -> handle);
  170.     LocalUnlock(hLocalMem);
  171.     return (HA_OK);
  172. }
  173.  
  174. /********************************************************************
  175. * SetHugeEl -                                                       *
  176. *   Sets the value of an array element.  This routine is exactly    *
  177. * the same as 'GetHugeEl' except that the memory copy is resversed. *
  178. ********************************************************************/
  179. int FAR pascal _export SetHugeEl(int hArray, long element, BYTE FAR *buffer)
  180. {
  181.     BYTE _huge          *ptr;               // pointer to array element
  182.     pDescrip            pArray;             // pointer to array descriptor
  183.  
  184.     if (hArray < 0 || hArray >= NumArrays)
  185.     return (HA_BADARRAY);               // illegal array handle
  186.  
  187.                         // point to proper descriptor
  188.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  189.  
  190.     if (pArray -> handle == NULL)  {
  191.     LocalUnlock(hLocalMem);
  192.     return (HA_BADARRAY);               // array hasn't been allocated
  193.     }
  194.     if ((pArray -> ubound < element) || (element < 0))  {
  195.     LocalUnlock(hLocalMem);
  196.     return (HA_SUBSCRIPT);              // subscript out of range
  197.     }
  198.                         // calculate pointer to element
  199.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  200.     ptr = ptr + element * pArray->recsize;
  201.     _fmemcpy(ptr, buffer, pArray -> recsize);   // copy data
  202.  
  203.     GlobalUnlock(pArray -> handle);
  204.     LocalUnlock(hLocalMem);
  205.     return (HA_OK);
  206. }
  207.  
  208. /********************************************************************
  209. * HugeErase -                                                       *
  210. *   Deletes an array and marks it as free in the descriptor table.  *
  211. * 'hArray' is the array to erase.                                   *
  212. ********************************************************************/
  213. int FAR pascal _export HugeErase(int hArray)
  214. {
  215.     pDescrip    pArray;                     // pointer to array descriptor
  216.  
  217.     if (hArray < 0 || hArray >= NumArrays)
  218.     return (HA_BADARRAY);               // illegal array handle
  219.  
  220.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  221.     if (pArray -> handle == NULL)  {
  222.     LocalUnlock(hLocalMem);
  223.     return (HA_BADARRAY);               // array hasn't been allocated yet
  224.     }
  225.  
  226.     GlobalFree(pArray -> handle);           // free the memory
  227.     pArray -> handle = NULL;
  228.  
  229.     LocalUnlock(hLocalMem);
  230.     return (HA_OK);
  231. }
  232.  
  233. /********************************************************************
  234. * NumHugeArrays -                                                   *
  235. *   Returns the number of free entries in the array descriptor table*
  236. ********************************************************************/
  237. int FAR pascal _export NumHugeArrays(void)
  238. {
  239.     pDescrip            pArray;             // pointer to current descriptor
  240.     int                 num, i;             // number free so far
  241.  
  242.     pArray = (pDescrip) LocalLock(hLocalMem);
  243.     for (i = 0, num = 0; i < NumArrays; i++, pArray++)
  244.     if (pArray -> handle == NULL)
  245.         ++num;
  246.  
  247.     LocalUnlock(hLocalMem);
  248.     return (num);
  249. }
  250.  
  251.  
  252. /********************************************************************
  253. * HugeUbound -                                                      *
  254. *   Returns the upper bound of a given array                        *
  255. ********************************************************************/
  256. long FAR pascal _export HugeUbound(int hArray)
  257. {
  258.     pDescrip    pArray;                     // pointer to array descriptor
  259.     long    ubound;                     // upper bound of array
  260.  
  261.     if (hArray < 0 || hArray >= NumArrays)
  262.     return (HA_BADARRAY);               // illegal array handle
  263.  
  264.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  265.     if (pArray -> handle == NULL)  {
  266.     LocalUnlock(hLocalMem);
  267.     return (HA_BADARRAY);               // array hasn't been allocated yet
  268.     }
  269.  
  270.     ubound = pArray -> ubound;
  271.     LocalUnlock(hLocalMem);
  272.  
  273.     return (ubound);
  274. }
  275.  
  276.  
  277. /********************************************************************
  278. * HugeInt -                                                         *
  279. *   Same as GetHugeEl except that it explicitly returns an integer. *
  280. * Use this function when you are in an expression such as:          *
  281. *           i% = 5 * HugeInt(4, 5)                                  *
  282. *                                                                   *
  283. * NOTE: Because the user could store anything in the array element, *
  284. *       they will not know if the value returned is a real value or *
  285. *       if an error occured.  Use GetHugeEl if the error code must  *
  286. *       be checked.                                                 *
  287. ********************************************************************/
  288. int FAR pascal _export HugeInt(int hArray, long element)
  289. {
  290.     int     retval;
  291.  
  292.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  293.     return (retval);
  294. }
  295.  
  296.  
  297. /********************************************************************
  298. * HugeLong -                                                        *
  299. *   Returns an element of a long integer array.  (re. HugeInt)      *
  300. ********************************************************************/
  301. long FAR pascal _export HugeLong(int hArray, long element)
  302. {
  303.     long    retval;
  304.  
  305.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  306.     return (retval);
  307. }
  308.  
  309.  
  310.  
  311. /********************************************************************
  312. * HugeSingle -                                                      *
  313. *   Returns an element of a single precesion array.  (re. HugeInt)  *
  314. ********************************************************************/
  315. float FAR pascal _export HugeSingle(int hArray, long element)
  316. {
  317.     float  retval;
  318.  
  319.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  320.     return (retval);
  321. }
  322.  
  323.  
  324. /********************************************************************
  325. * HugeDouble -                                                      *
  326. *   Returns an element of a double precesion array.  (re. HugeInt)  *
  327. ********************************************************************/
  328. double FAR pascal _export HugeDouble(int hArray, long element)
  329. {
  330.     double  retval;
  331.  
  332.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  333.     return (retval);
  334. }
  335.  
  336.  
  337. /********************************************************************
  338. * HugeCurrency -                                                    *
  339. *   Returns an element of a currency array.  (re. HugeInt)          *
  340. ********************************************************************/
  341. currency FAR pascal _export HugeCurrency(int hArray, long element)
  342. {
  343.     return((currency) HugeDouble(hArray, element));
  344. }
  345.  
  346. /********************************************************************
  347. *   HugeAlloc -                                                     *
  348. * Allocates (or reallocates) global memory for an array.  The size  *
  349. * of the array is recsize * (ubound + 1) bytes.  The information    *
  350. * for the array is stored in the array descriptor pointed to by     *
  351. * 'pArray'.                                                         *
  352. *                                                                   *
  353. * Note:  See HugeDim for a discussion on array size limitations.    *
  354. ********************************************************************/
  355. int HugeAlloc(pDescrip pArray,int recsize,long ubound, BOOL realloc)
  356. {
  357.     HANDLE              handle;             // temp handle for alloc
  358.  
  359.     ++ubound;                               // ubound = #elements - 1
  360.     if (recsize * ubound > 0xffff)          // is size integer power two?
  361.     if ((recsize <= 0) || (((recsize - 1) & recsize) != 0))
  362.         return (HA_BADELEMENTSIZE);
  363.  
  364.     if (realloc)                            // allocate array
  365.     handle = GlobalReAlloc(pArray -> handle, recsize * ubound,
  366.                            GMEM_MOVEABLE | GMEM_ZEROINIT);
  367.     else
  368.     handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, recsize * ubound);
  369.  
  370.     if (handle == NULL)
  371.     return (HA_OUTOFMEMORY);            // out of memory
  372.  
  373.     pArray -> handle = handle;              // save new handle
  374.     pArray -> recsize = recsize;            // record element size
  375.     pArray -> ubound = ubound - 1;
  376.  
  377.     return (HA_OK);
  378. }
  379.